﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace CoreLims.Models.CoreLims
{
    using TestRelation = SampleTestRelation;

    public static class SampleTestRelationExtension
    {
        /// <summary>
        /// 根据 ID 获得一项关联信息
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="Id"></param>
        /// <returns></returns>
        public static TestRelation getTestRelation(this TestRelation tal, CoreLimsContext dbContext, string Id) => 
            dbContext.TestRelation.FirstOrDefault(m => m.Id == Id);

        /// <summary>
        /// 根据 测试定义ID 获得该测试关联的所有关系
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="TestDefinitionId"></param>
        /// <returns></returns>
        public static List<TestRelation> getTestRelationByTestDefinitionId(this TestRelation tal, CoreLimsContext dbContext, string TestDefinitionId) =>
            dbContext.TestRelation.Where(m => m.TestDefinitionId == TestDefinitionId).ToList();

        /// <summary>
        /// 根据 分析项ID 获得该分析项关联的测试
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="AnalytesId"></param>
        /// <returns></returns>
        public static List<TestRelation> getTestRelationByAnalytesId(this TestRelation tal, CoreLimsContext dbContext, string AnalytesId) =>
            dbContext.TestRelation.Where(m => m.AnalytesId == AnalytesId).ToList();

        /// <summary>
        /// 根据 测试ID 和 分析项ID 查询数据
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="TestDefinitionId"></param>
        /// <param name="AnalytesId"></param>
        /// <returns></returns>
        public static List<TestRelation> getTestRelationByTwoId(this TestRelation tal, CoreLimsContext dbContext, string TestDefinitionId, string AnalytesId) =>
            dbContext.TestRelation.Where(m => m.TestDefinitionId == TestDefinitionId && m.AnalytesId == AnalytesId).ToList();

        /// <summary>
        /// 根据 测试ID 和 指标集ID 查询数据
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="TestDefinitionId"></param>
        /// <param name="AnalytesId"></param>
        /// <returns></returns>
        public static List<TestRelation> getTestRelationBySpecCollectionId(this TestRelation tal, CoreLimsContext dbContext, string TestDefinitionId, string SpecCollectionId) =>
            dbContext.TestRelation.Where(m => m.TestDefinitionId == TestDefinitionId && m.SpecCollectionId == SpecCollectionId).ToList();

        /// <summary>
        /// 根据 测试ID 和 方法ID 查询数据
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="TestDefinitionId"></param>
        /// <param name="AnalytesId"></param>
        /// <returns></returns>
        public static List<TestRelation> getTestRelationByMethodId(this TestRelation tal, CoreLimsContext dbContext, string TestDefinitionId, string MethodId) =>
            dbContext.TestRelation.Where(m => m.TestDefinitionId == TestDefinitionId && m.MethodId == MethodId).ToList();

        /// <summary>
        /// 添加 测试关联的分析项
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static string AddTestRelation(this TestRelation tal, CoreLimsContext dbContext)
        {
            var list = tal.getTestRelationByTwoId(dbContext, tal.TestDefinitionId, tal.AnalytesId);
            if (list.Count > 0)
                return "该分析项已关联到当前测试！";

            tal.Id = SAMPLE._newId();
            var analyte = SAMPLE.Analyte.getAnalyte(dbContext, tal.AnalytesId);

            tal.DetectionTimes = 1;

            dbContext.Add(tal);
            dbContext.SaveChanges();
            return "测试关联的分析项添加成功！";
        }

        /// <summary>
        /// 添加 测试关联的指标集
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static string AddSpecCollection(this TestRelation tal, CoreLimsContext dbContext)
        {
            var list = tal.getTestRelationBySpecCollectionId(dbContext, tal.TestDefinitionId, tal.SpecCollectionId);
            if (list.Count > 0)
                return "该指标集已关联到当前测试！";

            tal.Id = SAMPLE._newId();
            tal.DetectionTimes = 1;
            tal.IsDefault = tal.CheckSpecCollection(dbContext);

            dbContext.Add(tal);
            dbContext.SaveChanges();
            return "测试关联的指标集添加成功！";
        }

        /// <summary>
        /// 添加 测试关联的方法
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static string AddMethod(this TestRelation tal, CoreLimsContext dbContext)
        {
            var list = tal.getTestRelationByMethodId(dbContext, tal.TestDefinitionId, tal.MethodId);
            if (list.Count > 0)
                return "该方法已关联到当前测试！";

            tal.Id = SAMPLE._newId();
            tal.DetectionTimes = 1;
            tal.IsDefault = tal.CheckMethod(dbContext);

            dbContext.Add(tal);
            dbContext.SaveChanges();
            return "测试关联的方法添加成功！";
        }

        /// <summary>
        /// 根据ID，删除一项关系
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="Id"></param>
        /// <returns></returns>
        public static string DeleteTestRelation(this TestRelation tal, CoreLimsContext dbContext, string Id)
        {
            TestRelation Tal = SAMPLE.TestRelation.getTestRelation(dbContext, Id);
            Tal.DeleteSpecCollection(dbContext);
            Tal.DeleteMethod(dbContext);

            dbContext.Remove(Tal);
            dbContext.SaveChanges();
            return "删除成功！";
        }

        /// <summary>
        /// 如果删除的是默认方法，则给下一项赋默认值
        /// </summary>
        /// <param name="Tal"></param>
        /// <param name="dbContext"></param>
        private static void DeleteMethod(this TestRelation Tal, CoreLimsContext dbContext)
        {
            if (Tal.MethodId != null && Tal.IsDefault == true)
            {
                var temp = dbContext.TestRelation
                    .FirstOrDefault(s => s.MethodId != Tal.MethodId && s.TestDefinitionId == Tal.TestDefinitionId && s.MethodId != null);
                if (temp != null)
                {
                    temp.IsDefault = true;
                    dbContext.Update(temp);
                }
            }
        }

        /// <summary>
        /// 如果删除的是默认指标集，则给下一项赋默认值
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="Tal"></param>
        private static void DeleteSpecCollection(this TestRelation Tal, CoreLimsContext dbContext)
        {
            if (Tal.SpecCollectionId != null && Tal.IsDefault == true)
            {
                var temp = dbContext.TestRelation
                    .FirstOrDefault(s => s.SpecCollectionId != Tal.SpecCollectionId && s.TestDefinitionId == Tal.TestDefinitionId && s.SpecCollectionId != null);
                if (temp != null)
                {
                    temp.IsDefault = true;
                    dbContext.Update(temp);
                }
            }
        }

        /// <summary>
        /// 更新计算规则
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="Id"></param>
        /// <param name="AcceptanceRules"></param>
        /// <returns></returns>
        public static string UpdateTestRelationCalculationRules(this TestRelation tal, CoreLimsContext dbContext, string Id, string CalculationRules)
        {
            TestRelation Tal = SAMPLE.TestRelation.getTestRelation(dbContext, Id);
            Tal.CalculationRules = CalculationRules;

            dbContext.Update(Tal);
            dbContext.SaveChanges();
            return "更新成功！";
        }

        public static string ClearTestRelationCalculationRules(this TestRelation tal, CoreLimsContext dbContext, string Id)
        {
            TestRelation Tal = SAMPLE.TestRelation.getTestRelation(dbContext, Id);
            Tal.CalculationRules = null;

            dbContext.Update(Tal);
            dbContext.SaveChanges();
            return "更新成功！";
        }

        /// <summary>
        /// 更新检测次数
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <param name="Id"></param>
        /// <param name="AcceptanceRules"></param>
        /// <returns></returns>
        public static string UpdateTestRelationDetectionTimes(this TestRelation tal, CoreLimsContext dbContext, string Id, string Times)
        {
            int count = 0;
            int.TryParse(Times, out count);

            if (count <= 0)
                return "检测次数必须是大于零的整数！";

            TestRelation Tal = SAMPLE.TestRelation.getTestRelation(dbContext, Id);
            Tal.DetectionTimes = count;

            dbContext.Update(Tal);
            dbContext.SaveChanges();
            return "更新成功！";
        }

        /// <summary>
        /// 根据字符串 SpecCollection 或 Method，将传入ID对应的 IsDefault 属性设置 true。
        /// 同时将其它关联设置为 false。
        /// </summary>
        /// <param name="method"></param>
        /// <param name="dbContext"></param>
        /// <param name="SpecCollectionOrMethod">SpecCollection 或 Method</param>
        /// <param name="Id">被设置为默认值的Id</param>
        /// <returns></returns>
        public static string UpdateIsDefault(this TestRelation tal, CoreLimsContext dbContext, string SpecCollectionOrMethod, string Id)
        {
            TestRelation temp = SAMPLE.TestRelation.getTestRelation(dbContext, Id);

            if (SpecCollectionOrMethod == "SpecCollection")
            {
                var specList = dbContext.TestRelation.Where(m => m.TestDefinitionId == temp.TestDefinitionId && m.SpecCollectionId != null).ToList();
                foreach (var spec in specList)
                {
                    spec.IsDefault = false;
                    dbContext.Update(spec);
                }
                temp.IsDefault = true;
                dbContext.Update(temp);
            }

            if (SpecCollectionOrMethod == "Method")
            {
                var methodList = dbContext.TestRelation.Where(m => m.TestDefinitionId == temp.TestDefinitionId && m.MethodId != null).ToList();
                foreach (var meth in methodList)
                {
                    meth.IsDefault = false;
                    dbContext.Update(meth);
                }
                temp.IsDefault = true;
                dbContext.Update(temp);
            }

            dbContext.SaveChanges();
            return "默认值更新成功！";
        }

        /// <summary>
        /// 检查当前测试是否包含指标集
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        private static bool CheckSpecCollection(this TestRelation tal, CoreLimsContext dbContext)
        {
            var a = dbContext.TestRelation.Where(s => s.TestDefinitionId == tal.TestDefinitionId && s.SpecCollectionId != null)
                .ToList().Count;

            if (a == 0)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 检查当前测试是否包含方法
        /// </summary>
        /// <param name="tal"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        private static bool CheckMethod(this TestRelation tal, CoreLimsContext dbContext)
        {
            var a = dbContext.TestRelation.Where(s => s.TestDefinitionId == tal.TestDefinitionId && s.MethodId != null)
                .ToList().Count;

            if (a == 0)
                return true;
            else
                return false;
        }

    }

}
